package net.guruqu.rvoView;

import java.awt.Canvas;
import java.io.File;
import java.util.HashMap;

import javax.swing.JFrame;

import com.gibbon.jme.context.JmeContext;
import com.gibbon.jme.context.lwjgl.LWJGLContext;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.util.export.Savable;
import com.jme.util.export.xml.XMLImporter;

public class ModelRepository {
	private static ThreadLocal<ModelRepository> threadModelRepository = new ThreadLocal<ModelRepository>();
	JmeContext modelContext;
	HashMap<String, Savable> repository;
	HashMap<String, String> loadList;
	ProgressMonitor monitor;
	boolean loaded;
	boolean inited;
	Object loadLock;
	Object initLock;
	{
		loadLock = new Object();
		repository = new HashMap<String, Savable>();
		loadList = new HashMap<String, String>();
		loaded = false;
		inited = false;
		initLock = new Object();
	}

	public void stow() {
		threadModelRepository.set(this);
	}

	public static ModelRepository get() {
		return threadModelRepository.get();
	}

	private void initContext() {
		try {
			modelContext = JmeContext.create(LWJGLContext.class,
					JmeContext.CONTEXT_CANVAS);
			modelContext.start();
			Canvas canvas = modelContext.getCanvas();
			JFrame mini = new JFrame();
			mini.getContentPane().add(canvas);
			mini.setUndecorated(true);
			mini.setVisible(true);
			mini.setSize(100, 100);
			modelContext.waitFor();
			mini.setVisible(false);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public ModelRepository() {
		try {
			new Thread() {
				@Override
				public void run() {
					try {
						initContext();
						synchronized (initLock) {
							initLock.notifyAll();
							inited = true;
						}

						XMLImporter xmlImporter = new XMLImporter();

						while (true) {
							synchronized (loadLock) {
								if (loaded)
									loadLock.wait();
								if (monitor != null)
									monitor.setProgress(0.1f);
								repository.clear();
								int lc = 0;
								for (String key : loadList.keySet()) {
									String fn = loadList.get(key);
									Savable s = xmlImporter.load(new File(fn));
									if(s instanceof Spatial){
										if(!(s instanceof Node)){
											Node n = new Node("Spatial Encapsulation");
											n.attachChild((Spatial)s);
											s=n;
											n.updateModelBound();
											n.updateRenderState();
										}
									}
									repository.put(key, s);
									monitor.setProgress(0.1f + 0.9f
											* lc
											/ loadList.size());
									lc++;
								}
								loaded = true;
								loadLock.notifyAll();
								if (monitor != null)
									monitor.setProgress(1f);
							}
						}

					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}.start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public HashMap<String, String> getLoadList() {
		return loadList;
	}

	public void setLoadList(HashMap<String, String> loadList) {
		this.loadList = loadList;
	}

	public JmeContext getModelContext() {
		return modelContext;
	}

	public HashMap<String, Savable> getRepository() {
		return repository;
	}

	public void loadModel() {
		synchronized (loadLock) {
			loaded = false;
			loadLock.notifyAll();
		}
	}

	public void waitFor() {
		synchronized (initLock) {
			if (!inited) {
				try {
					initLock.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	public void waitForLoad() {
		synchronized (loadLock) {
			while (!loaded) {
				try {
					loadLock.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	public ProgressMonitor getMonitor() {
		return monitor;
	}

	public void setMonitor(ProgressMonitor monitor) {
		this.monitor = monitor;
	}
}
